#include "FileSystem.h"
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>


FileSys* FileSystemInit(const char * DirPath)
{
    FileSys* fs = (FileSys*)malloc(sizeof(DirPath));
    if(fs == NULL)
    {
        printf("FileSystemInit malloc error!\n");
    }
    
    DIR *dir;
    if((dir = opendir(DirPath)) == NULL)
    {
        if(mkdir(DirPath,0777) != 0) //如果创建目录成功， 函数返回 ，表示操作成功。mkdir 0 如果创建目录失败， 函数返回 ，表示操作失败。mkdir-1
        {
            printf("创建文件夹失败!\n");
            free(fs);
            return NULL;
        }
        fs->dirPath = strdup(DirPath); //指定路径  的字符串复制到文件系统结构体  的  成员变量中
        return fs;
    }
    else
    {
        closedir(dir);
        fs->dirPath = strdup(DirPath);
        return fs;
    }
}

bool CreateNewDirInFs(FileSys *fs, const char *DirName)
{   
    char DirPath[1024] = {0};
    sprintf(DirPath,"%s/%s",fs->dirPath,DirName);
    if(mkdir(DirPath,0777) != 0)
    {   
        perror("mkdir");
        return false;
    }
    return true;
}

bool DeleteDirInFs(FileSys *fs, const char *DirName)
{   
     char DirPath[1024] = {0};
    sprintf(DirPath,"%s/%s",fs->dirPath,DirName);
    if(rmdir(DirPath) != 0)
    {
        perror("rmdir");
        return false;
    }
    return true;
}

bool isDirExist(FileSys *fs, const char *DirName)
{   
    DIR*dir = opendir(fs->dirPath); //打开一个目录流，将该目录的内容读取到一个  类型的指针中
    if(dir == NULL)
    {
        perror("isDirExist opendir");
        return false;
    }

    struct dirent * entry; //结构体指向的是目录流中的目录项，用于保存目录中每个条目的信息
    while((entry = readdir(dir)) != NULL) //一个  循环，它的目的是遍历指定目录中的所有条目。
    {
        if(strcmp(entry->d_name,DirName) == 0) //使用了  函数来比较当前目录项的名字（存储在  中）与某个目标目录名  是否相等
        {
            closedir(dir);
            return true;
        }
    }
    closedir(dir);
    return false;
}


void WriteFileToFs(FileSys * fs,const char * DirName,const char * fileName,void *p,size_t size)
{
      char filePath[1024] = {0};
      sprintf(filePath,"%s/%s/%s",fs->dirPath,DirName,fileName);

      FILE*f = fopen(filePath,"a");
      fwrite(p,size,1,f);
      fclose(f);
}

char*getFileSize(const char* DirPath,const char * fileName)
{
    char filePath[1024] = {0};
    sprintf(filePath,"%s/%s",DirPath,fileName);

    struct stat st;
    stat(filePath,&st);

    char size[20] = {0};
    sprintf(size,"%ld",st.st_size);
    return strdup(size);
    
}

char *GetFileList(FileSys *fs, const char *DirName)
{   
    char list[1024] = {0};
    char DirPath[1024] = {0};
    sprintf(DirPath,"%s/%s",fs->dirPath,DirName);
    DIR*dir = opendir(DirPath);
    if(dir == NULL)
    {
        return NULL;
    }
    struct dirent *entry;
    while((entry = readdir(dir)) != NULL)
    {
        if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0)
         continue;

         char*size = getFileSize(DirPath,entry->d_name);
         strcat(list,entry->d_name);
         strcat(list,";");
         strcat(list,size);
         strcat(list,",");
         free(size);
    }
    if(strlen(list) == 0)
    {   
        closedir(dir);
         return NULL;
    }
    list[strlen(list) - 1] = '\0';
    closedir(dir);
    return strdup(list);
}
struct PacketFile
{
    FILE *f;
    long FileSize;
    long currentPosition;
};

PackFile *PacketFileInit(const char *FilePath) //函数的声明，指定了函数的返回类型为 PackFile*，函数名为 PacketFileInit，接受一个指向常量字符的指针 FilePath 作为参数，表示文件路径。
{   
    PackFile *pf = (PackFile*)malloc(sizeof(PackFile)); //使用 malloc 函数分配内存，大小为 PackFile 结构体的大小，并将其强制类型转换为 PackFile* 类型的指针。这个指针 pf 指向分配的内存块，用于存储 PackFile 结构体的数据
    if(pf == NULL)
    {
        printf("PackerFileInit malloc error!\n");
        return NULL;
    }

    pf->f = fopen(FilePath,"r"); //打开指定路径的文件，以只读方式打开，并将文件指针赋值给 pf->f
    if(pf->f == NULL)
    {
        printf("打开|%s|文件失败！\n",FilePath);
        free(pf);
        return NULL;
    }

    fseek(pf->f,0,SEEK_END); //将文件指针移到文件末尾，以便获取文件大小
     pf->FileSize = ftell(pf->f); //获取文件大小，并将其保存到 pf->FileSize 中。
    fseek(pf->f,0,SEEK_SET); //将文件指针移回文件开头，以便后续读取文件内容

    pf->currentPosition = 0; //将当前位置初始化为文件开头
    return pf;
    
}

void ReadFromFile(PackFile *f, void *p, int *size) //函数的声明，指定了函数的返回类型为 void，函数名为 ReadFromFile，接受一个 PackFile 结构体指针 f，一个指向内存的指针 p，以及一个整型指针 size 作为参数。
{
    if(*size + f->currentPosition > f->FileSize) //检查要读取的数据大小加上当前位置是否超过了文件大小。如果超过了，就将要读取的大小调整为剩余的文件大小
    {
        *size = f->FileSize -f->currentPosition; //如果要读取的数据大小超过了文件剩余大小，就将 size 调整为剩余的文件大小。


    }
    fread(p,*size,1,f->f); //使用 fread 函数从文件中读取数据，将读取的数据存储到内存指针 p 所指向的位置，读取的大小为 size，每次读取一个数据块
    f->currentPosition += *size; //将文件指针移动到已读取的位置之后，以便下一次读取
}

bool IsFileEnd(PackFile *f) //这是函数的声明，指定了函数的返回类型为布尔值 bool，函数名为 IsFileEnd，接受一个 PackFile 结构体指针 f 作为参数
{   
    return f->currentPosition == f->FileSize; //feof 函数用于检查文件流的结束标志。如果文件已经结束，则 feof 返回非零值，否则返回零。将 feof 返回的结果与零进行比较，如果不等于零，则说明文件已经到达末尾，返回 true；否则返回 false
    
}

void GetDownFileSize(PackFile*f,int *size)
{
    *size = f->FileSize;
}

void ClearPacketFile(PackFile*f)
{
      fclose(f->f);
      free(f);
}
